Imports Microsoft.VisualBasic
Imports System.ComponentModel
Imports System.Web.UI
Imports System.Text
Imports AjaxControlToolkit

Namespace WebControls

    <DefaultProperty("Text")> _
    <ValidationProperty("Text")> _
    <ToolboxData("<{0}:MaskTextBox runat=""server""></{0}:MaskTextBox>")> _
    Public Class MaskTextBox
        Inherits CompositeControl

        Private mTextBox As TextBox
        Private requireValidator As RequiredFieldValidator
        Private expressValidator As RegularExpressionValidator
        Private ajaxExtender As ValidatorCalloutExtender

        Private mTextMaskType As MaskType = MaskType.None
        Private mAllowEmpty As Boolean = False
        Private mAddValidatorControl As Boolean = True
        Private mAddAjaxtExtender As Boolean = True
        Private mValidationGroup As String

        Public Property Text() As String
            Get
                Me.EnsureChildControls()
                Return Me.mTextBox.Text
            End Get
            Set(ByVal value As String)
                Me.EnsureChildControls()
                mTextBox.Text = value
            End Set
        End Property

        <Category("Behavior")> _
        Public Property MaxLength() As Integer
            Get
                Me.EnsureChildControls()
                Return Me.mTextBox.MaxLength
            End Get
            Set(ByVal value As Integer)
                Me.EnsureChildControls()
                Me.mTextBox.MaxLength = value
            End Set
        End Property

        <DesignOnly(True)> _
        <Description("Auto add RequiredFieldValidator and RegularExpressionValidator ")> _
        Public Property AddValidatorControl() As Boolean
            Set(ByVal value As Boolean)
                mAddValidatorControl = value
            End Set
            Get
                Return mAddValidatorControl
            End Get
        End Property

        <DesignOnly(True)> _
        <Description("Auto add AjaxValidatorExtender")> _
        Public Property AddAjaxtExtender() As Boolean
            Set(ByVal value As Boolean)
                mAddAjaxtExtender = value
            End Set
            Get
                Return mAddAjaxtExtender
            End Get
        End Property

        <DefaultValue("")> _
        Public Property TextMaskType() As MaskType
            Set(ByVal value As MaskType)
                mTextMaskType = value
            End Set
            Get
                Return mTextMaskType
            End Get
        End Property

        Public Property AllowEmpty() As Boolean
            Get
                Return mAllowEmpty
            End Get
            Set(ByVal value As Boolean)
                mAllowEmpty = value
            End Set
        End Property

        Public Overrides Property Width() As System.Web.UI.WebControls.Unit
            Get
                Me.EnsureChildControls()
                Return mTextBox.Width
            End Get
            Set(ByVal value As System.Web.UI.WebControls.Unit)
                Me.EnsureChildControls()
                mTextBox.Width = value
            End Set
        End Property

        Public Property ValidationGroup() As String
            Get
                Return mValidationGroup
            End Get
            Set(ByVal value As String)
                mValidationGroup = value
            End Set
        End Property

        Public Overrides Property CssClass() As String
            Get
                Me.EnsureChildControls()
                Return Me.mTextBox.CssClass
            End Get
            Set(ByVal value As String)
                Me.EnsureChildControls()
                Me.mTextBox.CssClass = value
            End Set
        End Property

        Protected Overrides Sub CreateChildControls()
            Controls.Clear()

            mTextBox = New TextBox
            mTextBox.ID = MyBase.ID + "_txt"
            Me.Controls.Add(mTextBox)

            requireValidator = New RequiredFieldValidator
            requireValidator.ID = MyBase.ID + "_reqValidator"
            requireValidator.ControlToValidate = mTextBox.ID
            requireValidator.ValidationGroup = ValidationGroup
            requireValidator.ErrorMessage = "This field is required."
            Controls.Add(requireValidator)

            expressValidator = New RegularExpressionValidator
            expressValidator.ID = MyBase.ID + "_expValidator"
            expressValidator.ControlToValidate = mTextBox.ID
            expressValidator.ValidationGroup = ValidationGroup
            expressValidator.ValidationExpression = RegexString()
            expressValidator.ErrorMessage = "Invalid input."
            Controls.Add(expressValidator)

            ajaxExtender = New ValidatorCalloutExtender
            ajaxExtender.TargetControlID = requireValidator.ID
            Controls.Add(ajaxExtender)

            Me.ChildControlsCreated = True
            'MyBase.CreateChildControls()
        End Sub

        Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
            mTextBox.RenderControl(writer)
            If Not DesignMode Then
                If AddValidatorControl Then
                    If AddAjaxtExtender AndAlso (Not mAllowEmpty OrElse mTextMaskType = MaskType.Email) Then
                        ajaxExtender.RenderControl(writer)
                    End If

                    If Not mAllowEmpty Then
                        requireValidator.RenderControl(writer)
                    End If

                    If mTextMaskType = MaskType.Email Then
                        expressValidator.RenderControl(writer)
                    End If
                End If
            End If
        End Sub

        Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
            Select Case mTextMaskType
                Case MaskType.Currency, MaskType.Number
                    Me.mTextBox.Attributes.Add("onpaste", "return false;")
                    Me.mTextBox.Style.Add("text-align", "right")

                Case MaskType.Email
                    If AddAjaxtExtender Then ajaxExtender.TargetControlID = expressValidator.ID
            End Select

            requireValidator.Display = IIf(AddAjaxtExtender, ValidatorDisplay.None, ValidatorDisplay.Dynamic)
            expressValidator.Display = IIf(AddAjaxtExtender, ValidatorDisplay.None, ValidatorDisplay.Dynamic)

            ScriptManager.RegisterClientScriptBlock(Me.Page, Page.GetType(), "checkTextBox", GetJs, False)
            Dim js As String = String.Format("TextValueChange(this,event,'{0}');", TextMaskType.ToString)
            Me.mTextBox.Attributes.Add("onkeypress", js)
        End Sub

        Protected Overrides Sub RecreateChildControls()
            If Not ChildControlsCreated Then
                MyBase.RecreateChildControls()
            End If
        End Sub

        Private Function RegexString() As String
            Select Case TextMaskType
                Case MaskType.Currency
                    Return "(^[1-9]\d*(\.\d{1,3})?$)|(^0\.(([1-9]{1,3})|(\d{1}[1-9])|([1-9]\d{1}))$)"
                Case MaskType.Email
                    Return "\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
                Case MaskType.Number
                    Return "^\d*$"
                Case MaskType.NumberString
                    Return "^\w*$"
            End Select
            Return ""
        End Function

        Private Function GetJs() As String
            Dim js As String = "<script type=""text/javascript"" >function TextValueChange(obj,e,maskType){var txtval=obj.value;var key = document.all ? e.keyCode : e.charCode;switch (maskType){case ""Currency"":if((key < 48||key > 57)&&key != 46){document.all ? e.keyCode = 0 :  e.preventDefault();}else{if(key == 46){if(txtval.indexOf('.') != -1||txtval.length == 0)document.all ? e.keyCode = 0 :  e.preventDefault();}}break;case ""Number"": if(key < 48||key > 57){document.all ? e.keyCode = 0 :  e.preventDefault();}break;}}</script> "
            Return js
        End Function

        Public Enum MaskType
            None = 0
            Currency
            Number
            NumberString
            Email
        End Enum

    End Class

End Namespace
